home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / pyshared / Onboard / KeyCommon.py < prev    next >
Encoding:
Python Source  |  2008-03-03  |  7.9 KB  |  234 lines

  1. # -*- coding: UTF-8 -*-
  2.  
  3. from math import sqrt
  4.  
  5. BASE_PANE_TAB_HEIGHT = 40
  6.  
  7. CHAR_ACTION, KEYSYM_ACTION, KEYCODE_ACTION, MODIFIER_ACTION, MACRO_ACTION, SCRIPT_ACTION = range(1,7)
  8.  
  9. # KeyCommon hosts the abstract classes for the various types of Keys.
  10. # UI-specific keys should be defined in KeyGtk or KeyKDE files.
  11. # NOTE: I really don't like the way pointWithinKey() is handled.
  12. # I won't change it now, but we should strive for maximum
  13. # efficency of inheritance (move the poinWithinKey() to
  14. # the Key class and only tweak it for the other classes.
  15.  
  16.  
  17. class KeyCommon:
  18.     ''' a library-independent key class. Specific 
  19.         rendering options are stored elsewhere. '''
  20.  
  21.     action_type = None
  22.     """Type of action to do when key is pressed."""
  23.  
  24.     action = None
  25.     """Data used in action."""
  26.  
  27.     pane = None
  28.     """Pane that this key is on."""
  29.  
  30.     on = False
  31.     """True when key is being pressed."""
  32.  
  33.     stuckOn = False
  34.     """When key is sticky and pressed twice."""
  35.  
  36.     sticky = False
  37.     """Keys that stay stuck when pressed like modifiers."""
  38.  
  39.     beingScanned = False
  40.     """True when onboard is in scanning mode and key is highlighted"""
  41.  
  42.     def __init__(self,pane):
  43.         self.pane = pane
  44.         
  45.     def setProperties(self, action_type, action, labels, sticky, 
  46.                                                     fontOffsetX, fontOffsetY):
  47.  
  48.         self.fontOffsetX = fontOffsetX # Mostly for odd shaped keys.
  49.         self.fontOffsetY = fontOffsetY
  50.         self.action = action
  51.         self.action_type = action_type
  52.         self.sticky = sticky
  53.         self.labels = labels
  54.     
  55.     def paintFont(self, xScale, yScale, x, y, context = None):
  56.         ''' Key.paintFont() paints a font. All context-related
  57.             actions are UI-dependent. Thus, they are moved 
  58.             to overriddable classes.'''
  59.  
  60.         if hasattr(self,"labels"):
  61.             if xScale < yScale:
  62.                 self.fontScale = xScale
  63.             else: 
  64.                 self.fontScale = yScale # oddly python doesn't do scope in if statements.
  65.             if self.pane.keyboard.mods[1]:
  66.                 if self.pane.keyboard.mods[128] and self.labels[4]:
  67.                     label = self.labels[4]
  68.                 elif self.labels[2]:
  69.                     label = self.labels[2]
  70.                 elif self.labels[1]:
  71.                     label = self.labels[1]
  72.                 else:
  73.                     label = self.labels[0]
  74.             
  75.             elif self.pane.keyboard.mods[128] and self.labels[4]:
  76.                 label = self.labels[3]
  77.             
  78.             elif self.pane.keyboard.mods[2]:
  79.                 if self.labels[1]:
  80.                     label = self.labels[1]
  81.                 else:
  82.                     label = self.labels[0]
  83.             else:
  84.                 label = self.labels[0]
  85.  
  86.             #TODO This is a hack we should make sure that the text is always scaled down so it fits within the key.
  87.             if len(label) > 4:
  88.                 self.fontScale -= 1.1
  89.             elif len(label) > 1:
  90.                 self.fontScale -= 1.1
  91.  
  92.             if self.fontScale < 0.5:
  93.                 self.fontScale = 0.5
  94.  
  95.             self.moveObject((x + self.fontOffsetX) * xScale + 4, (y +self.fontOffsetY) * yScale - 0.03*self.pane.fontSize*sqrt(self.fontScale), context)
  96.  
  97.             self.createLayout(label)
  98.  
  99. class TabKeyCommon(KeyCommon):
  100.     ''' class for those tabs up the right hand side '''
  101.     def __init__(self, keyboard, width, pane):
  102.         KeyCommon.__init__(self, pane)
  103.  
  104.         self.width = width
  105.         self.keyboard = keyboard
  106.         self.modifier = None # what for?
  107.         self.sticky = True
  108.  
  109.     def pointWithinKey(self, widget, mouseX, mouseY):
  110.         ''' does exactly what the name says - checks for the 
  111.             mouse within a key. returns bool. '''
  112.         if (mouseX > self.keyboard.kbwidth 
  113.             and mouseY > self.height*self.index + BASE_PANE_TAB_HEIGHT 
  114.             and mouseY < self.height*(self.index + 1)+ BASE_PANE_TAB_HEIGHT):
  115.             return True
  116.         else:
  117.             return False
  118.  
  119.    
  120.     def paint(self, context = None):
  121.         ''' paints the TabKey object '''
  122.         #mhb TODO: make it UI independent
  123.         self.height = (self.keyboard.height / len(self.keyboard.panes)) - (BASE_PANE_TAB_HEIGHT / len(self.keyboard.panes))
  124.         self.index = self.keyboard.panes.index(self.pane)
  125.     
  126.     
  127. class BaseTabKeyCommon(KeyCommon):
  128.     ''' class for the tab that brings you to the base pane '''
  129.     def __init__(self, keyboard, width):
  130.         KeyCommon.__init__(self, None)
  131.        
  132.         self.width = width
  133.         self.keyboard = keyboard
  134.         self.modifier = None # what for?
  135.         self.sticky = False
  136.  
  137.     def pointWithinKey(self, widget, mouseX, mouseY):
  138.         if (mouseX > self.keyboard.kbwidth 
  139.             and mouseY < BASE_PANE_TAB_HEIGHT):
  140.             return True
  141.         else:
  142.             return False
  143.  
  144.    
  145.     def paint(self,context=None):
  146.         '''Don't draw anything for this key'''
  147.         pass
  148.  
  149. class LineKeyCommon(KeyCommon):
  150.     ''' class for keyboard buttons made of lines '''
  151.     def __init__(self, pane, coordList, fontCoord, rgba):
  152.         KeyCommon.__init__(self, pane)
  153.         self.coordList = coordList
  154.         self.fontCoord = fontCoord
  155.         self.rgba = rgba
  156.         
  157.     def pointCrossesEdge(self, x, y, xp1, yp1, sMouseX, sMouseY):
  158.         ''' Checks whether a point, when scanning from top left crosses edge'''
  159.         return ((((y <= sMouseY) and ( sMouseY < yp1)) or  
  160.             ((yp1 <= sMouseY) and (sMouseY < y))) and 
  161.             (sMouseX < (xp1 - x) * (sMouseY - y) / (yp1 - y) + x))
  162.         
  163.     
  164.     def pointWithinKey(self, widget, mouseX, mouseY):
  165.         '''Checks whether point is within shape.
  166.            Currently does not bother trying to work out
  167.            curved paths accurately. '''
  168.         x = self.coordList[0]
  169.         y = self.coordList[1]
  170.         c = 2
  171.         coordLen = len(self.coordList)
  172.         within = False
  173.         
  174.         sMouseX = mouseX/self.pane.xScale
  175.         sMouseY = mouseY/self.pane.yScale
  176.         
  177.         while not c == coordLen:
  178.  
  179.             xp1 = self.coordList[c+1]
  180.             yp1 = self.coordList[c+2]
  181.             try:
  182.                 if self.coordList[c] == "L":
  183.                     within = (self.pointCrossesEdge(x,y,xp1,yp1,sMouseX,sMouseY) ^ within) # a xor        
  184.                     c +=3
  185.                     x = xp1
  186.                     y = yp1
  187.                         
  188.                 else:   
  189.                     xp2 = self.coordList[c+3]
  190.                     yp2 = self.coordList[c+4]
  191.                     xp3 = self.coordList[c+5]
  192.                     yp3 = self.coordList[c+6]
  193.                     within = (self.pointCrossesEdge(x,y,xp3,yp3,sMouseX,sMouseY) ^ within) # a xor 
  194.                     x = xp3
  195.                     y = yp3
  196.                     c += 7
  197.  
  198.                 
  199.  
  200.             except ZeroDivisionError, (strerror):
  201.                 print strerror
  202.                 print "x: %f, y: %f, yp1: %f" % (x,y,yp1)
  203.         return within
  204.         
  205.     def paint(self, xScale, yScale, context = None):
  206.         ''' This class is quite hard to abstract, so all of its
  207.             processing lies now in the UI-dependent class.¬†'''
  208.                
  209.     def paintFont(self, xScale, yScale, context = None):
  210.         KeyCommon.paintFont(self, xScale, yScale, self.coordList[0], self.coordList[1], context)
  211.             
  212.     
  213.     
  214. class RectKeyCommon(KeyCommon):
  215.     ''' An abstract class for rectangular keyboard buttons '''
  216.     def __init__(self, pane, x, y, width, height, rgba):
  217.         KeyCommon.__init__(self,pane)
  218.         self.x = x
  219.         self.y = y
  220.         self.width = width
  221.         self.height = height
  222.         self.rgba = rgba      
  223.       
  224.     def pointWithinKey(self, widget, mouseX, mouseY):
  225.         if(mouseX / self.pane.xScale > self.x and mouseX / self.pane.xScale < (self.x + self.width)
  226.            and mouseY / self.pane.yScale > self.y and mouseY / self.pane.yScale < (self.y + self.height)):
  227.            return True
  228.         else:
  229.            return False
  230.          
  231.     
  232.     def paint(self, xScale, yScale, context = None):
  233.         pass
  234.